package com.siecom.transport.handler;

import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import com.google.gson.Gson;
import com.google.protobuf.ByteString;
import com.siecom.constconfig.ConstDefine;
import com.siecom.constconfig.ErrorDefine;
import com.siecom.hostservice.MainActivity;
import com.siecom.module.DeviceCallback;
import com.siecom.module.DeviceInterface;
import com.siecom.proto.Message;
import com.siecom.signaturepad.views.SignaturePad;
import com.siecom.tool.ByteTool;
import com.siecom.tool.FileUnits;
import com.siecom.tool.ImageUnit;
import com.siecom.tool.LogUtil;
import com.siecom.tool.Point;
import com.siecom.transport.CommServer;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by zhq on 2017/2/6.
 */

public class SignatureHandler implements ServiceHandler {
    private static ExecutorService threadPool = Executors.newFixedThreadPool(1);
    private static final String TAG = "SignatureHandler";

    private CommServer server;
    private Timer timer;

    private String tempMsgId = null;
    @Override
    public void onReceive(CommServer server, Message.siecomproto msg,String message) {
        this.server = server;
        Log.e("SignatureHandler", "onReceive");
        disposeMessage(msg);
    }

    public void disposeMessage(Message.siecomproto msg) {

        switch (msg.getCmd()) {
            case ConstDefine.SIGNATURE_SM4_REQUEST:
                loadSignMainKey(msg); //写入本地主密钥
//                setSM4PrimaryKey(msg);

                break;

            case  ConstDefine.SIGNATURE_SM2_REQUEST:
                transSM2PublicKey(msg);
                break;
            case ConstDefine.SIGNATURE_REQUEST:
                signature(msg);
                break;
            case ConstDefine.SIGNATURE_CANCEL_REQUEST:
                cancelTask(msg);
                break;

        }

    }


    private void loadSignMainKey(Message.siecomproto msg){
        String mainKey ;
        int index,type;
        try {
            JSONObject jb = new JSONObject(msg.getRequest());
            mainKey = jb.optString("mainKey");
            index = jb.optInt("index");
            type = jb.optInt("type");
        } catch (JSONException e) {
            throw new RuntimeException(e);
        }
        LogUtil.e(TAG,"signMainKey == " + mainKey);
        DeviceInterface.setSignMainKey(new DeviceCallback() {
            @Override
            public void onStart() {

            }

            @Override
            public void onError(Bundle bundle) {
                com.siecom.proto.Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
                Log.e(msg.getMsgid()+"==",msg.getCmd()+"");
                msgBuilder.setModule(msg.getModule());
                msgBuilder.setMsgid(msg.getMsgid());
                msgBuilder.setCmd(msg.getCmd() + 1);
                msgBuilder.setRespond(bundle.getString("message"));
                msgBuilder.setError(bundle.getInt("code"));
                com.siecom.proto.Message.siecomproto respondMsg = msgBuilder.build();
                server.sendToRemote(respondMsg);
                MainActivity.playVoice(ConstDefine.OPERATE_FAIL);
            }

            @Override
            public void onSuccess(Bundle bundle) {
                com.siecom.proto.Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
                Log.e(msg.getMsgid()+"==",msg.getCmd()+"");
                msgBuilder.setModule(msg.getModule());
                msgBuilder.setMsgid(msg.getMsgid());
                msgBuilder.setCmd(msg.getCmd() + 1);
                msgBuilder.setRespond(bundle.getString("data"));
                msgBuilder.setError(0);
                com.siecom.proto.Message.siecomproto respondMsg = msgBuilder.build();
                server.sendToRemote(respondMsg);
                MainActivity.playVoice(ConstDefine.OPERATE_SUCC);
            }

            @Override
            public void onCompleted(Bundle bundle) {

            }
        },mainKey, type, index,false);
    }

    private void setSM4PrimaryKey(Message.siecomproto msg) {
        byte[] sm4 = msg.getExtion().toByteArray();
        DeviceInterface.setSM4PrimaryKey(new DeviceCallback() {
          @Override
          public void onStart() {

          }

          @Override
          public void onError(Bundle bundle) {
              com.siecom.proto.Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
              Log.e(msg.getMsgid()+"==",msg.getCmd()+"");
              msgBuilder.setModule(msg.getModule());
              msgBuilder.setMsgid(msg.getMsgid());
              msgBuilder.setCmd(msg.getCmd() + 1);
              msgBuilder.setRespond(bundle.getString("message"));
              msgBuilder.setError(bundle.getInt("code"));
              com.siecom.proto.Message.siecomproto respondMsg = msgBuilder.build();
              server.sendToRemote(respondMsg);
              MainActivity.playVoice(ConstDefine.OPERATE_FAIL);
          }

          @Override
          public void onSuccess(Bundle bundle) {
              com.siecom.proto.Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
              Log.e(msg.getMsgid()+"==",msg.getCmd()+"");
              msgBuilder.setModule(msg.getModule());
              msgBuilder.setMsgid(msg.getMsgid());
              msgBuilder.setCmd(msg.getCmd() + 1);
              msgBuilder.setRespond(bundle.getString("data"));
              msgBuilder.setError(0);
              com.siecom.proto.Message.siecomproto respondMsg = msgBuilder.build();
              server.sendToRemote(respondMsg);
              MainActivity.playVoice(ConstDefine.OPERATE_SUCC);
          }

          @Override
          public void onCompleted(Bundle bundle) {

          }
      },sm4,false);

    }

    public void transSM2PublicKey(Message.siecomproto msg){
        DeviceInterface.transSM2PublicKey(new DeviceCallback() {
            @Override
            public void onStart() {

            }

            @Override
            public void onError(Bundle bundle) {
                com.siecom.proto.Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();

                msgBuilder.setModule(msg.getModule());
                msgBuilder.setMsgid(msg.getMsgid());
                msgBuilder.setCmd(msg.getCmd() + 1);
                msgBuilder.setRespond(bundle.getString("message"));
                msgBuilder.setError(bundle.getInt("code"));
                com.siecom.proto.Message.siecomproto respondMsg = msgBuilder.build();
                server.sendToRemote(respondMsg);

            }

            @Override
            public void onSuccess(Bundle bundle) {
                com.siecom.proto.Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
                Log.e(msg.getMsgid()+"==",msg.getCmd()+"");
                msgBuilder.setModule(msg.getModule());
                msgBuilder.setMsgid(msg.getMsgid());
                msgBuilder.setCmd(msg.getCmd() + 1);
                msgBuilder.setRespond(bundle.getString("data"));
                msgBuilder.setError(0);
                com.siecom.proto.Message.siecomproto respondMsg = msgBuilder.build();
                server.sendToRemote(respondMsg);
            }

            @Override
            public void onCompleted(Bundle bundle) {

            }
        },false);

    }

    public void cancelTask(Message.siecomproto msg){
        MainActivity.cancelSignaturePad();
        if(timer!=null){
            timer.cancel();
        }
        com.siecom.proto.Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
        Log.e(msg.getMsgid()+"==",msg.getCmd()+"");
        msgBuilder.setModule(msg.getModule());
        msgBuilder.setMsgid(msg.getMsgid());
        msgBuilder.setCmd(msg.getCmd() + 1);
        msgBuilder.setRespond("signature cancel");
        msgBuilder.setError(0);
        com.siecom.proto.Message.siecomproto respondMsg = msgBuilder.build();
        server.sendToRemote(respondMsg);

        if (tempMsgId != null){
            msgBuilder.setModule(msg.getModule());
            msgBuilder.setMsgid(tempMsgId);
            msgBuilder.setCmd(ConstDefine.SIGNATURE_RESPOND);
            msgBuilder.setRespond("signature cancel");
            msgBuilder.setError(ErrorDefine.SIGNATURE_ADMIN_CANCEL);
            com.siecom.proto.Message.siecomproto respondMsg2 = msgBuilder.build();
            server.sendToRemote(respondMsg2);
        }

    }
    private void signature(Message.siecomproto msg){
        tempMsgId = msg.getMsgid();
        boolean isAllowBlank = false;  //是否允许空白签名。
        int type = -1;  // 加密类型  1 des  2 SM4
        int index = 0;
        try {
            JSONObject jb = new JSONObject(msg.getRequest());
            if (jb.has("width"))
                SignaturePad.width = jb.getInt("width");

        } catch (JSONException e) {
            e.printStackTrace();
        }
        try {
            JSONObject jb = new JSONObject(msg.getRespond()); //新加的json参数
            isAllowBlank = jb.optBoolean("isBlank");
            isTransparent = jb.optBoolean("transparent");
            LogUtil.e(TAG,"isAllowBlank == " + isAllowBlank);
            String workKey = jb.optString("workKey");
             type = jb.optInt("type");
             index = jb.optInt("index");
            if (workKey.length() >= 16 ){ //国密
                DeviceInterface.setSignWorkKey(index,type,workKey);
            }
            if (jb.has("width"))
                SignaturePad.width = jb.getInt("width");

        } catch (JSONException e) {
            e.printStackTrace();
        }
        MainActivity.showSignaturePad( msg.getTimeout());

        /**
         * 超时处理
         */
        TimerTask task = new TimerTask() {
            @Override
            public void run() {

                Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
                msgBuilder.setMsgid(msg.getMsgid());
                msgBuilder.setModule(msg.getModule());
                msgBuilder.setCmd(ConstDefine.SIGNATURE_RESPOND);
                msgBuilder.setError(ErrorDefine.SIGNATURE_TIMEOUT);
                msgBuilder.setRespond(ErrorDefine.getErrorDescribe(ErrorDefine.SIGNATURE_TIMEOUT));
                com.siecom.proto.Message.siecomproto respondMsg = msgBuilder.build();
                server.sendToRemote(respondMsg);

                MainActivity.cancelSignaturePad();
            }
        };
        if(timer!=null){
            timer.cancel();
        }
        timer = new Timer();
        timer.schedule(task, msg.getTimeout());

        MainActivity.setSignatureCancleListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                com.siecom.proto.Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();

                msgBuilder.setModule(msg.getModule());
                msgBuilder.setMsgid(msg.getMsgid());
                msgBuilder.setCmd(msg.getCmd() + 1);
                msgBuilder.setRespond("signature cancel");
                msgBuilder.setError(ErrorDefine.SIGNATURE_USER_CANCEL);
                com.siecom.proto.Message.siecomproto respondMsg = msgBuilder.build();
                server.sendToRemote(respondMsg);
                MainActivity.cancelSignaturePad();
                if(timer!=null){
                    timer.cancel();
                }
            }
        });
        boolean finalIsAllowBlank = isAllowBlank;
        int finalType = type;
        int finalIndex = index;
        MainActivity.setSignatureListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(MainActivity.isClean){
                    if (!finalIsAllowBlank){
                        MainActivity.playVoice(7);
                        return;
                    }

                }

                v.setEnabled(false);
                Runnable r = new Runnable() {
                    @Override
                    public void run() {

                        MainActivity.endSignature(new MainActivity.SignatureCallball(){

                            @Override
                            public void endSign(int res, byte[] data) {

                                if(res==0x90){
                                    Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
                                    msgBuilder.setMsgid(msg.getMsgid());
                                    msgBuilder.setModule(msg.getModule());
                                    msgBuilder.setRespond("sign");
                                    msgBuilder.setCmd(ConstDefine.SIGNATURE_RESPOND);
                                    msgBuilder.setError(0);
                                    ByteString signByte = ByteString.copyFrom(data);
                                    msgBuilder.setExtion(signByte);
                                    Message.siecomproto respondMsg = msgBuilder.build();
                                    server.sendToRemote(respondMsg);
                                }else if(res == 10086){ //不加密
                                    Message.siecomproto.Builder msgBuilderData = com.siecom.proto.Message.siecomproto.newBuilder();
                                    msgBuilderData.setMsgid(msg.getMsgid());
                                    msgBuilderData.setModule(msg.getModule());

                                    msgBuilderData.setCmd(ConstDefine.SIGNATURE_RESPOND);
                                    msgBuilderData.setError(0);
                                    byte[] bytes = ByteTool.getInfoBytesFromObject(SignaturePad.mPoint);
                                    String p = new Gson().toJson(SignaturePad.mPoint);//以json方式传递
                                    p = formatPoint(SignaturePad.mPoint);
//                                    LogUtil.e(TAG,"mPoints == " + p);
//                                    msgBuilderData.setRequest(p);//发送字符字节

                                    if (finalType > 0){  //要做加密
                                        p = DeviceInterface.setSignEncryptTrack(ByteTool.byte2hex(p.getBytes()),finalType,finalIndex);
                                        LogUtil.e(TAG,"加密后的trackPoint = " + p);
                                    }
                                    msgBuilderData.setRespond(p);
//                                    ByteString signByte = ByteString.copyFrom(bytes);//发送
//                                    msgBuilderData.setExtion(signByte);
                                    Message.siecomproto respondMsgData = msgBuilderData.build();
//                                    server.sendToRemote(respondMsgData);

                                    MainActivity.cancelSignaturePad();

                                }

                            }
                        });

                        //发送图片数据
                        sendSignBitmap(msg);

                        if(timer!=null){
                            timer.cancel();
                        }


                    }
                };
                threadPool.submit(r);


            }
        });

    }

    boolean isTransparent = false;  // 是否是透明背景的签名图片
    public void sendSignBitmap(Message.siecomproto msg){
        Log.e("setSignatureListener","click");

        Message.siecomproto.Builder msgBuilder = com.siecom.proto.Message.siecomproto.newBuilder();
        msgBuilder.setMsgid(msg.getMsgid());
        msgBuilder.setModule(msg.getModule());
        msgBuilder.setCmd(ConstDefine.SIGNATURE_RESPOND);
        msgBuilder.setError(0);


        JSONObject jb;
        int scale = 5;
        int clearBlank = 0;
        int quality = 90;
        int withTrack = 1;

        try {
            jb = new JSONObject(msg.getRequest());
            if (jb.has("scale"))
                scale = jb.getInt("scale");

            if (jb.has("clear"))
                clearBlank = jb.getInt("clear");

            if (jb.has("quality"))
                quality = jb.getInt("quality");

            if (jb.has("tk"))
                withTrack = jb.getInt("tk");


        } catch (JSONException e) {
            e.printStackTrace();
        }
        LogUtil.e(TAG,"scale == " + scale + "\n quality == " + quality +
                "\n clearBlank == " + clearBlank + "\n withTrack == " + withTrack);
        //轨迹数据
        if (withTrack == 1)
            msgBuilder.setRespond(formatPoint(SignaturePad.mPoint));

        float s = scale * 0.1f;
        Bitmap signatureBmp = MainActivity.getSignaturePadBitmap(isTransparent);
        LogUtil.e(TAG,"原始大小 == " + signatureBmp.getByteCount());
//        FileUnits.saveImage(signatureBmp,"sdcard/sign1.png");
        if(clearBlank == 1){
            signatureBmp = ImageUnit.clearBlank(signatureBmp,1);
            LogUtil.e(TAG,"除边后大小 == " + signatureBmp.getByteCount());
//            FileUnits.saveImage(signatureBmp,"sdcard/sign2.png");
        }
        if(s > 0 && s < 1){
            signatureBmp = matrixCompress(signatureBmp,s); //大小压缩
            LogUtil.e(TAG,"matrix后大小 == " + signatureBmp.getByteCount());
//            FileUnits.saveImage(signatureBmp,"sdcard/sign3.png");
        }

        ByteArrayOutputStream output = new ByteArrayOutputStream();//初始化一个流对象
        if (isTransparent)
            signatureBmp.compress(Bitmap.CompressFormat.PNG, quality, output);
        else
            signatureBmp.compress(Bitmap.CompressFormat.JPEG, quality, output);

        signatureBmp.recycle();//自由选择是否进行回收
        byte[] result = output.toByteArray();//转换成功了
        try {
            output.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        ByteString bitmapByte = ByteString.copyFrom(result);
        msgBuilder.setExtion(bitmapByte);
        LogUtil.e(TAG,"签名图片大小：" + bitmapByte.size() );
//                        ByteString signByte = ByteString.copyFrom(ByteTool.getInfoBytesFromObject(SignaturePad.mPoint));
//                        msgBuilder.setMsgidBytes(bitmapByte);
        Message.siecomproto respondMsg = msgBuilder.build();
        server.sendToRemote(respondMsg);
    }

    public Bitmap matrixCompress(Bitmap bmp,float size){
        Matrix matrix = new Matrix();
        matrix.setScale(size,size);
        return Bitmap.createBitmap(bmp,0,0,bmp.getWidth(),bmp.getHeight(),matrix,true);
    }

    public String formatPoint(ArrayList<Point> points){
        if(points == null || points.size() <= 0){
            return "";
        }
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < points.size(); i++) {

            sb.append(points.get(i).getX()).append(":");
            sb.append(points.get(i).getY()).append(",");
            sb.append(points.get(i).getT()).append(":");
        }
        return sb.toString();
    }

}
